package net.pws.common.httpclient;

import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;

import net.pws.common.jackson.JsonUtils;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;


public class DefaultHttpClientAgent implements HttpClientAgent {
    
    private static final Log logger = LogFactory.getLog(DefaultHttpClientAgent.class);
    
    private static class HttpClientAgentHolder {
        private static HttpClientAgent instance = new DefaultHttpClientAgent();
    }
    
    public static HttpClientAgent getInstance() {
        return HttpClientAgentHolder.instance;
    }
    
    private DefaultHttpClient client;
    
    public DefaultHttpClientAgent() {
        client = newHttpClient();
    }
    
    private DefaultHttpClient newHttpClient() {
        HttpParams httpParameters = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParameters, 60000);
        HttpConnectionParams.setSoTimeout(httpParameters, 60000);
        
        SchemeRegistry schReg = new SchemeRegistry();
        schReg.register(new Scheme("http",
                                   PlainSocketFactory.getSocketFactory(),
                                   80));
        schReg.register(new Scheme("https",
                                   SSLSocketFactory.getSocketFactory(),
                                   443));
        ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(httpParameters,
                                                                                    schReg);
        
        return new DefaultHttpClient(connectionManager, httpParameters);
    }
    
    public String get(HttpClientRequest provider) {
        if (provider == null || StringUtils.isBlank(provider.getUrl())) {
            throw new HttpClientException("HttpParameterProvider为空或请求的URL为空！");
        }
        
        HttpGet get = new HttpGet(provider.getUrlWithParams());
        addHeaders(get, provider.getHeaders());
        
        return sendRequest(get);
    }
    
    public Map getJson(HttpClientRequest provider) {
        String result = get(provider);
        return JsonUtils.parseJson(result, Map.class);
    }
    
    public Map postJson(HttpClientRequest provider) {
        String result = post(provider);
        return JsonUtils.parseJson(result, Map.class);
    }
    
    public String post(HttpClientRequest provider) {
        if (provider == null || StringUtils.isBlank(provider.getUrl())) {
            throw new HttpClientException("HttpParameterProvider为空或请求的URL为空！");
        }
        
        HttpPost post = new HttpPost(provider.getUrl());
        post.setEntity(provider.getEntity());
        addHeaders(post, provider.getHeaders());
        
        return sendRequest(post);
    }
    
    public boolean testConnection(String url) {
        HttpGet get = new HttpGet(url);
        try {
            sendRequest(get);
            return true;
        }
        catch (Exception e) {
            return false;
        }
    }
    
    private String sendRequest(HttpUriRequest request) {
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        try {
            String result = client.execute(request, responseHandler);
            logger.debug("The response:" + result);
            return result;
        }
        catch (Exception e) {
            throw new HttpClientException("访问远程服务器失败！", e);
        }
        finally {
            // request.abort();
            // client.getConnectionManager().shutdown();
        }
    }
    
    private void addHeaders(HttpUriRequest request, Properties headers) {
        if (headers == null) {
            return;
        }
        
        for (Enumeration<String> propNames = (Enumeration<String>) headers.propertyNames(); propNames.hasMoreElements();) {
            String propName = propNames.nextElement();
            request.addHeader(propName, headers.getProperty(propName));
        }
    }
    
}
